﻿namespace Microsoft.VisualStudio.IDE.ToolboxControlsInstaller
{
    using Microsoft.VisualStudio.OLE.Interop;
    using MS.Internal.Package;
    using System;
    using System.Collections;
    using System.Runtime.InteropServices;

    public abstract class DictionaryControl : RegisteredControl
    {
        private IDictionary properties;

        protected DictionaryControl(string typeName, IDictionary properties) : base(typeName)
        {
            this.properties = properties;
        }

        [DllImport("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
        internal static extern IntPtr GlobalFree(HandleRef handle);
        [DllImport("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
        internal static extern IntPtr GlobalLock(HandleRef handle);
        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
        internal static extern bool GlobalUnlock(HandleRef handle);
        public bool IsEqualTo(IDataObject dObj)
        {
            IDictionary dictionary = ToolDictionaryFromData(dObj, this.DictionaryFormat);
            if (dictionary != null)
            {
                try
                {
                    if (((dictionary["CreationAssemblyName"].ToString() == this.Properties["CreationAssemblyName"].ToString()) && (dictionary["CreationTypeName"].ToString() == this.Properties["CreationTypeName"].ToString())) && (dictionary["ToolTypeName"].ToString() == this.Properties["ToolTypeName"].ToString()))
                    {
                        return true;
                    }
                }
                catch (NullReferenceException)
                {
                }
            }
            return false;
        }

        internal static IDictionary ToolDictionaryFromData(IDataObject data, int clipFormat)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            FORMATETC[] pFormatetc = new FORMATETC[1];
            FORMATETC formatetc = new FORMATETC {
                cfFormat = (ushort) clipFormat,
                dwAspect = 1,
                tymed = 1,
                lindex = -1,
                ptd = IntPtr.Zero
            };
            pFormatetc[0] = formatetc;
            if (data.QueryGetData(pFormatetc) != 0)
            {
                return null;
            }
            STGMEDIUM[] pRemoteMedium = new STGMEDIUM[1];
            pRemoteMedium[0].pUnkForRelease = IntPtr.Zero;
            pRemoteMedium[0].tymed = 1;
            data.GetData(pFormatetc, pRemoteMedium);
            IntPtr unionmember = pRemoteMedium[0].unionmember;
            IDictionary dictionary = null;
            try
            {
                IntPtr toolPtr = GlobalLock(new HandleRef(null, unionmember));
                try
                {
                    dictionary = ToolEncoder.Decode(toolPtr);
                }
                finally
                {
                    GlobalUnlock(new HandleRef(null, toolPtr));
                }
            }
            finally
            {
                GlobalFree(new HandleRef(null, unionmember));
            }
            return dictionary;
        }

        public abstract int DictionaryFormat { get; }

        public IDictionary Properties
        {
            get
            {
                return this.properties;
            }
            set
            {
                this.properties = value;
            }
        }
    }
}

